﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Bootloader.zlgcan
{

    public static class ZLG27Algorithm
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate int ZLGKeyDelegate(
            byte[] iSeedArray,
            ushort iSeedArraySize,
            uint iSecurityLevel,
            [MarshalAs(UnmanagedType.LPStr)] string iVariant,
            byte[] iKeyArray,
            ref ushort iKeyArraySize
        );

        private static IntPtr _dllHandle = IntPtr.Zero;
        private static ZLGKeyDelegate _zlgKeyFunc = null;
        private static string _dllPath = ".\\Security.dll";

        public static void SetDllPath(string dllPath)
        {
            if (_dllHandle != IntPtr.Zero)
            {
                FreeLibrary(_dllHandle);
                _dllHandle = IntPtr.Zero;
                _zlgKeyFunc = null;
            }
            _dllPath = dllPath;
            EnsureDllLoaded();
        }

        public static byte[] Securityalgorithm(byte[] seed, uint securityLevel)
        {
            // 返回空
            if (seed == null || seed.Length == 0)
                return Array.Empty<byte>();

            byte[] keyArray = new byte[256];
            ushort keySize = (ushort)keyArray.Length;

            // 调用你封装的 4 参数 ZLGKey（注意：不要传 iSeedArraySize 和 iVariant！）
            int result = ZLG27Algorithm.ZLGKey(
                iSeedArray: seed,
                iSecurityLevel: securityLevel,
                iKeyArray: keyArray,
                iKeyArraySize: ref keySize
            );

            if (result == 0)
            {
                // 成功：截取有效部分并返回
                byte[] actualKey = new byte[keySize];
                Array.Copy(keyArray, actualKey, keySize);
                return actualKey; // 返回密钥
            }
            else
            {
                return Array.Empty<byte>();
            }
        }

        private static int ZLGKey(
                byte[] iSeedArray,
                uint iSecurityLevel,
                byte[] iKeyArray,
                ref ushort iKeyArraySize)
        {
            // 按你指定的方式：iVariant 固定为空字符串
            string iVariant = "";
            ushort iSeedArraySize = (ushort)(iSeedArray?.Length ?? 0);

            return _zlgKeyFunc(iSeedArray, iSeedArraySize, iSecurityLevel, iVariant, iKeyArray, ref iKeyArraySize);
        }

        private static void EnsureDllLoaded()
        {
            if (_dllHandle == IntPtr.Zero)
            {
                _dllHandle = LoadLibrary(_dllPath);
                if (_dllHandle == IntPtr.Zero)
                    throw new DllNotFoundException($"未找到DLL文件: {_dllPath}");

                IntPtr funcPtr = GetProcAddress(_dllHandle, "ZLGKey");
                if (funcPtr == IntPtr.Zero)
                {
                    FreeLibrary(_dllHandle);
                    _dllHandle = IntPtr.Zero;
                    throw new EntryPointNotFoundException("错误的DLL文件");
                }

                _zlgKeyFunc = Marshal.GetDelegateForFunctionPointer<ZLGKeyDelegate>(funcPtr);
            }
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool FreeLibrary(IntPtr hModule);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    }

}